# -*- coding: utf-8 -*-
# owner: shenyi

from typing import List, Optional
from src.providers.base import BaseProvider
from src.models.instance import (
    CreateInstanceRequest,
    DeleteInstanceRequest,
    InstanceTypeRequest,
    AvailableInstanceTypeRequest,
    QueryInstanceRequest
)
from src.models.responses import (
    CreateResponse,
    DeleteResponse,
    InstanceTypeResponse,
    AvailableZonesInstanceTypeResponse,
    InstanceType as ResponseInstanceType,
    InstanceListResponse,
    Instance as ResponseInstance
)
from src.core import logger, credentials

from google.cloud import compute_v1
from google.api_core.exceptions import ClientError


class Compute(BaseProvider):
    """
    Google Cloud Compute 实现类
    运行在云上不用指定GOOGLE_APP_ENGINE_CREDENTIALS，线下需要指定GOOGLE_APP_ENGINE_CREDENTIALS=/path/to/credentials.json
    """

    def __init__(self, **config):
        super().__        # 可选：将 client 作为实例属性，支持依赖注入（便于 mock 测试）
        self._client = config.get("client")
        google_credis = credentials().google()
        self.project_id = google_credis.get("project_id")

    async def create_instance(self, request: CreateInstanceRequest) -> CreateResponse:
        """
        创建 Google Cloud 实例

        Docs: https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.services.instances.InstancesClient#google_cloud_compute_v1_services_instances_InstancesClient_insert
        """
            
        client = compute_v1.InstancesClient()

        # 配置实例请求
        instance = compute_v1.Instance(
            name=request.host_name,
            machine_type=f"zones/{request.zone_id}/machineTypes/{request.instance_type}",
            labels={tag["key"]: tag["value"] for tag in request.tag} if request.tag else {},
            service_accounts=[
                compute_v1.ServiceAccount(
                    email="default",
                    scopes=["https://www.googleapis.com/auth/cloud-platform"]
                )
            ],
            network_interfaces=[
                compute_v1.NetworkInterface(
                    network=f"global/networks/{request.v_switch_id}",
                )
            ],
        )

        # 配置启动磁盘
        boot_disk = compute_v1.AttachedDisk()
        boot_disk.auto_delete = True
        boot_disk.boot = True
        boot_disk.initialize_params = compute_v1.AttachedDiskInitializeParams(
            source_image=f"global/images/{request.image_id}"
        )
        instance.disks = [boot_disk]

        # 配置数据盘
        if request.data_disk:
            for data in request.data_disk:
                data_disk = compute_v1.AttachedDisk()
                data_disk.auto_delete = True
                data_disk.boot = False
                disk_type = data["category"] if data["category"] else "pd-balanced"
                data_disk.initialize_params = compute_v1.AttachedDiskInitializeParams(
                    disk_size_gb=request.request_disk_size if request.request_disk_size > data["size"] else data["size"],
                    disk_type=f"zones/{request.zone_id}/diskTypes/{disk_type}",
                )
                instance.disks.append(data_disk)

        req = compute_v1.InsertInstanceRequest(
            instance_resource=instance,
            project=self.project_id,
            zone=request.zone_id,
        )

        try:
            response = client.insert(request=req)
            logger.info(f"创建实例成功，实例ID：{response.name}")
            return CreateResponse(
                status_code=200, 
                message="success", 
                instance_ids=[response.name]
            )
        except Exception as e:
            error_msg = str(e)
            logger.error(f"Failed to create Google Cloud instance: {error_msg}")
            return CreateResponse(status_code=400, message=error_msg)

    async def delete_instance(self, request: DeleteInstanceRequest) -> DeleteResponse:
        """
        删除 Google Cloud 实例

        Docs: https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.services.instances.InstancesClient#google_cloud_compute_v1_services_instances_InstancesClient_delete
        """
            
        client = compute_v1.InstancesClient()
        
        req = compute_v1.DeleteInstanceRequest(
            instance=request.instance_id,
            project=self.project_id,
            zone=request.zone_id,
        )

        try:
            client.delete(request=req)
            return DeleteResponse(status_code=200, message="success")
        except ClientError as e:
            logger.exception(f"Failed to delete Google Cloud instance {request.instance_id}: {str(e)}")
            return DeleteResponse(status_code=e.code, message=str(e))
        except Exception as e:
            error_msg = str(e)
            logger.error(f"Failed to delete Google Cloud instance {request.instance_id}: {error_msg}")
            return DeleteResponse(status_code=400, message=error_msg)

    async def list_instance_types(self, request: InstanceTypeRequest) -> InstanceTypeResponse:
        """
        获取实例规格列表
        
        Docs: https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.services.machine_types.MachineTypesClient#google_cloud_compute_v1_services_machine_types_MachineTypesClient_list
        """
            
        client = compute_v1.MachineTypesClient()
        
        req = compute_v1.ListMachineTypesRequest(
            project=self.project_id,
            zone=request.zone_id,
        )
        
        try:
            page_result = client.list(request=req)
            machine_types = []
            for machine_type in page_result:
                machine_types.append(ResponseInstanceType(
                    instance_type_id=machine_type.name,
                    cpu_core_count=machine_type.guest_cpus,
                    memory_size=machine_type.memory_mb / 1024,  # 转换为GB
                ))
            
            return InstanceTypeResponse(
                status_code=200,
                message="success",
                instance_spec=machine_types
            )
        except Exception as e:
            error_msg = str(e)
            logger.error(f"Failed to list Google Cloud machine types: {error_msg}")
            return InstanceTypeResponse(
                status_code=400,
                message=error_msg,
                instance_spec=[]
            )

    async def list_available_instance_types(self, request: AvailableInstanceTypeRequest) -> AvailableZonesInstanceTypeResponse:
        """
        获取可用的实例规格
        
        Docs: https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.services.machine_types.MachineTypesClient#google_cloud_compute_v1_services_machine_types_MachineTypesClient_list
        """
        # 这里可以实现获取可用实例类型的逻辑
        return AvailableZonesInstanceTypeResponse(
            status_code=200,
            message="success",
            instance_spec=[]
        )
    
    async def health_check(self) -> bool:
        """
        检查云服务是否正常
        """
        return True
           
    async def list_instances(self, request: QueryInstanceRequest) -> InstanceListResponse:
        """
        列出指定区域的所有实例

        Docs: https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.services.instances.InstancesClient#google_cloud_compute_v1_services_instances_InstancesClient_list
        """
        try:
            client = compute_v1.InstancesClient()
            req = compute_v1.ListInstancesRequest(
                project=self.project_id,
                zone=request.zone_id,
            )

            # 使用分页迭代器自动处理多页结果
            page_result = client.list(request=req)
            instances: List[ResponseInstance] = []

            for instance in page_result:
                # 提取公网 IP（可能不存在）
                public_ip: Optional[str] = None
                if instance.network_interfaces:
                    access_configs = instance.network_interfaces[0].access_configs
                    if access_configs:
                        public_ip = access_configs[0].nat_ip

                # 提取私网 IP
                private_ip: Optional[str] = None
                if instance.network_interfaces:
                    private_ip = instance.network_interfaces[0].network_i_p

                # 提取 machine_type 的类型名（如 "n1-standard-1"）
                machine_type = ""
                if instance.machine_type:
                    machine_type = instance.machine_type.split("/")[-1]

                # 提取 zone 名称（如 "us-central1-a"）
                zone = ""
                if instance.zone:
                    zone = instance.zone.split("/")[-1]

                instances.append(
                    ResponseInstance(
                        instance_id=instance.id,  # 使用 numeric ID 更标准
                        name=instance.name,
                        instance_type_id=machine_type,
                        zone_id=zone,
                        status=instance.status,
                        public_ip=public_ip,
                        private_ip=private_ip,
                        created_at=instance.creation_timestamp,  # 可选字段
                        labels=instance.labels,  # 可选：标签
                    )
                )

            return InstanceListResponse(
                status_code=200,
                message="Success",
                instances=instances
            )
        except Exception as e:
            logger.error(f"Unexpected error listing instances: {e}", exc_info=True)
            return InstanceListResponse(
                status_code=500,
                message="Internal server error",
                instances=[]
            )